home *** CD-ROM | disk | FTP | other *** search
- char *connv = "CONNECT Command for DG AOS/VS, 5A(044) 10 Oct 92";
-
- /* C K D C O N -- Dumb terminal connection to remote system, for AOS/VS */
- /*
- Author: Frank da Cruz (fdc@columbia.edu, FDCCU@CUVMA.BITNET),
- Columbia University Center for Computing Activities.
- First released January 1985.
- Copyright (C) 1985, 1992, Trustees of Columbia University in the City of New
- York. Permission is granted to any individual or institution to use, copy, or
- redistribute this software so long as it is not sold for profit, provided this
- copyright notice is retained.
- */
-
- /* This module brought up to 5A by Eugenia Harris at Data General. */
-
- #nolist
- #include "ckcdeb.h" /* Common things first */
- #include <signal.h> /* Signals */
- #include <errno.h> /* Error numbers */
- #include <setjmp.h>
-
- /* Kermit-specific includes */
-
- #include "ckcasc.h" /* ASCII characters */
- #include "ckcker.h" /* Kermit things */
- #include "ckucmd.h" /* For xxesc() prototype */
- #include "ckcnet.h" /* Network symbols */
- #ifndef NOCSETS
- #include "ckcxla.h" /* Character set translation */
- #endif /* NOCSETS */
-
- #ifdef datageneral
- #include <sgtty.h>
- #include <multitask.h>
- #include <packets:normal_io.h>
- #list
-
- extern short idel_tbl[7] = {0x4,0,0,0,0,0,0}; /* delimiter table -- */
- /* defaults to CR only*/
- /* Globals and defines for DG multi-tasking connect command */
- void readfromcommline(); /* listener sub-task */
- extern int ttyfd,ttyfdout;
- #define TASKID 17 /* task id of readfromcommline task */
- #define TASKPRI 200 /* priority of readfromcommline (was 2) */
- #define STACK 02000 /* default stack size (was 0) */
- #define MAXINBUF 2048
- static int inbufsize = MAXINBUF;
- extern long times();
- #endif /* datageneral */
-
- /* Internal function prototypes */
-
- _PROTOTYP( VOID doesc, (char) );
- _PROTOTYP( VOID logchar, (char) );
- _PROTOTYP( int hconne, (void) );
-
- #ifndef SIGUSR1 /* User-defined signals */
- #define SIGUSR1 30
- #endif /* SIGUSR1 */
-
- #ifndef SIGUSR2
- #define SIGUSR2 31
- #endif /* SIGUSR2 */
-
- /* External variables */
-
- extern int local, escape, duplex, parity, flow, seslog, sessft, debses,
- mdmtyp, ttnproto, cmask, cmdmsk, network, nettype, deblog, sosi, tnlm,
- xitsta, what, ttyfd, quiet, backgrd, tt_crd, tn_nlm;
- extern long speed;
- extern char ttname[], sesfil[], myhost[],*ccntab[];
- #ifdef NETCONN
- extern int tn_init;
- #endif /* NETCONN */
-
- #ifndef NOSETKEY /* Keyboard mapping */
- extern KEY *keymap; /* Single-character key map */
- extern MACRO *macrotab; /* Key macro pointer table */
- static MACRO kmptr = NULL; /* Pointer to current key macro */
- #endif /* NOSETKEY */
-
- /* Global variables local to this module */
-
- static int quitnow = 0, /* <esc-char>Q was typed */
- dohangup = 0, /* <esc-char>H was typed */
- sjval = 0, /* Setjump return value */
- goterr = 0, /* I/O error flag */
- active = 0, /* Lower fork active flag */
- inshift = 0; /* SO/SI shift state */
- outshift = 0;
-
- static char kbuf[10], *kbp; /* Keyboard buffer & pointer */
- static PID_T parent_id = (PID_T)0; /* Process id of main task */
-
- static char *ibp; /* Input buffer pointer */
- static int ibc = 0; /* Input buffer count */
- #define IBUFL 4096 /* Input buffer length */
-
- static char *obp; /* Output buffer pointer */
- static int obc = 0; /* Output buffer count */
- #define OBUFL 1024 /* Output buffer length */
-
- #define TMPLEN 200 /* Temp buffer length */
-
- #ifdef DYNAMIC
- static char *ibuf, *obuf, *temp; /* Input, output, & temp buffers */
- #else
- static char ibuf[IBUFL], obuf[OBUFL], temp[TMPLEN];
- #endif /* DYNAMIC */
-
- /* Character-set items */
-
- #ifndef NOCSETS
- #ifdef CK_ANSIC /* ANSI C prototypes... */
- extern CHAR (*xls[MAXTCSETS+1][MAXFCSETS+1])(CHAR); /* Character set */
- extern CHAR (*xlr[MAXTCSETS+1][MAXFCSETS+1])(CHAR); /* translation functions */
- static CHAR (*sxo)(CHAR); /* Local translation functions */
- static CHAR (*rxo)(CHAR); /* for output (sending) terminal chars */
- static CHAR (*sxi)(CHAR); /* and for input (receiving) terminal chars. */
- static CHAR (*rxi)(CHAR);
- #else /* Not ANSI C... */
- extern CHAR (*xls[MAXTCSETS+1][MAXFCSETS+1])(); /* Character set */
- extern CHAR (*xlr[MAXTCSETS+1][MAXFCSETS+1])(); /* translation functions. */
- static CHAR (*sxo)(); /* Local translation functions */
- static CHAR (*rxo)(); /* for output (sending) terminal chars */
- static CHAR (*sxi)(); /* and for input (receiving) terminal chars. */
- static CHAR (*rxi)();
- #endif /* CK_ANSIC */
- extern int language; /* Current language. */
- static int langsv; /* For remembering language setting. */
- extern struct csinfo fcsinfo[]; /* File character set info. */
- extern int tcsr, tcsl; /* Terminal character sets, remote & local. */
- static int tcs; /* Intermediate ("transfer") character set. */
-
- #ifndef NOESCSEQ
- /*
- As of edit 178, the CONNECT command will skip past ANSI escape sequences
- to avoid translating the characters within them. This allows the CONNECT
- command to work correctly when connected to a remote host that uses a
- 7-bit ISO 646 national character set, in which characters like '[' would
- normally be translated into accented characters, ruining the terminal's
- interpretation (and generation) of escape sequences.
-
- Escape sequences of non-ANSI/ISO-compliant terminals are not handled.
- */
- #ifndef SKIPESC
- #define SKIPESC
- #endif /* SKIPESC */
- /*
- States for the escape-sequence recognizer.
- */
- #define ES_NORMAL 0 /* Normal, not in escape sequence */
- #define ES_GOTESC 1 /* Current character is ESC */
- #define ES_ESCSEQ 2 /* Inside an escape sequence */
- #define ES_GOTCSI 3 /* Inside a control sequence */
- #define ES_STRING 4 /* Inside DCS,OSC,PM, or APC string */
- #define ES_TERMIN 5 /* 1st char of string terminator */
-
- static int
- skipesc = 0, /* Skip over ANSI escape sequences */
- inesc = ES_NORMAL; /* State of sequence recognizer */
- /*
- ANSI escape sequence handling. Only the 7-bit form is treated, because
- translation is not a problem in the 8-bit environment, in which all GL
- characters are ASCII and no translation takes place. So we don't check
- for the 8-bit single-character versions of CSI, DCS, OSC, APC, or ST.
- Here is the ANSI sequence recognizer state table, followed by the code
- that implements it.
-
- Definitions:
- CAN = Cancel 01/08 Ctrl-X
- SUB = Substitute 01/10 Ctrl-Z
- DCS = Device Control Sequence 01/11 05/00 ESC P
- CSI = Control Sequence Introducer 01/11 05/11 ESC [
- ST = String Terminator 01/11 05/12 ESC \
- OSC = Operating System Command 01/11 05/13 ESC ]
- PM = Privacy Message 01/11 05/14 ESC ^
- APC = Application Program Command 01/11 05/15 ESC _
-
- ANSI escape sequence recognizer:
-
- State Input New State ; Commentary
-
- NORMAL (start) ; Start in NORMAL state
-
- (any) CAN NORMAL ; ^X cancels
- (any) SUB NORMAL ; ^Z cancels
-
- NORMAL ESC GOTESC ; Begin escape sequence
- NORMAL other ; NORMAL control or graphic character
-
- GOTESC ESC ; Start again
- GOTESC [ GOTCSI ; CSI
- GOTESC P STRING ; DCS introducer, consume through ST
- GOTESC ] STRING ; OSC introducer, consume through ST
- GOTESC ^ STRING ; PM introducer, consume through ST
- GOTESC _ STRING ; APC introducer, consume through ST
- GOTESC 0..~ NORMAL ; 03/00 through 17/14 = Final character
- GOTESC other ESCSEQ ; Intermediate or ignored control character
-
- ESCSEQ ESC GOTESC ; Start again
- ESCSEQ 0..~ NORMAL ; 03/00 through 17/14 = Final character
- ESCSEQ other ; Intermediate or ignored control character
-
- GOTCSI ESC GOTESC ; Start again
- GOTCSI @..~ NORMAL ; 04/00 through 17/14 = Final character
- GOTCSI other ; Intermediate char or ignored control char
-
- STRING ESC TERMIN ; Maybe have ST
- STRING other ; Consume all else
-
- TERMIN \ NORMAL ; End of string
- TERMIN other STRING ; Still in string
- */
- /*
- chkaes() -- Check ANSI Escape Sequence.
- Call with EACH character in input stream.
- Sets global inesc variable according to escape sequence state.
- */
- VOID
- #ifdef CK_ANSIC
- chkaes(char c)
- #else
- chkaes(c) char c;
- #endif /* CK_ANSIC */
- /* chkaes */ {
-
- if (c == CAN || c == SUB) /* CAN and SUB cancel any sequence */
- inesc = ES_NORMAL;
- else /* Otherwise */
- switch (inesc) { /* enter state switcher */
-
- case ES_NORMAL: /* NORMAL state */
- if (c == ESC) /* Got an ESC */
- inesc = ES_GOTESC; /* Change state to GOTESC */
- break; /* Otherwise stay in NORMAL state */
-
- case ES_GOTESC: /* GOTESC state */
- if (c == '[') /* Left bracket after ESC is CSI */
- inesc = ES_GOTCSI; /* Change to GOTCSI state */
- else if (c > 057 && c < 0177) /* Final character '0' thru '~' */
- inesc = ES_NORMAL; /* Back to normal */
- else if (c == 'P' || (c > 0134 && c < 0140)) /* P, [, ^, or _ */
- inesc = ES_STRING; /* Switch to STRING-absorption state */
- else if (c != ESC) /* ESC in an escape sequence... */
- inesc = ES_ESCSEQ; /* starts a new escape sequence */
- break; /* Intermediate or ignored ctrl char */
-
- case ES_ESCSEQ: /* ESCSEQ -- in an escape sequence */
- if (c > 057 && c < 0177) /* Final character '0' thru '~' */
- inesc = ES_NORMAL; /* Return to NORMAL state. */
- else if (c == ESC) /* ESC ... */
- inesc = ES_GOTESC; /* starts a new escape sequence */
- break; /* Intermediate or ignored ctrl char */
-
- case ES_GOTCSI: /* GOTCSI -- In a control sequence */
- if (c > 077 && c < 0177) /* Final character '@' thru '~' */
- inesc = ES_NORMAL; /* Return to NORMAL. */
- else if (c == ESC) /* ESC ... */
- inesc = ES_GOTESC; /* starts over. */
- break; /* Intermediate or ignored ctrl char */
-
- case ES_STRING: /* Inside a string */
- if (c == ESC) /* ESC may be 1st char of terminator */
- inesc = ES_TERMIN; /* Go see. */
- break; /* Absorb all other characters. */
-
- case ES_TERMIN: /* May have a string terminator */
- if (c == '\\') /* which must be backslash */
- inesc = ES_NORMAL; /* If so, back to NORMAL */
- else /* Otherwise */
- inesc = ES_STRING; /* Back to string absorption. */
- }
- }
- #endif /* NOESCSEQ */
- #endif /* NOCSETS */
-
- /* Connect state parent/child communication signal handlers */
-
- static jmp_buf con_env; /* Environment pointer for connect errors */
- /*
- Note: Some C compilers (e.g. Cray UNICOS) interpret the ANSI C standard
- about setjmp() in a way that disallows constructions like:
-
- if ((var = setjmp(env)) == 0) ...
-
- which prevents the value returned by longjmp() from being used at all.
- So the following handlers set a global variable instead.
- */
- static
- SIGTYP
- conn_int(foo) int foo; { /* Modem read failure handler, */
- signal(SIGUSR1,SIG_IGN); /* Disarm the interrupt */
- sjval = 1; /* Set global variable */
- longjmp(con_env,sjval); /* Notifies parent process to stop */
- }
-
- static
- SIGTYP
- mode_chg(foo) int foo; {
-
- signal(SIGUSR2,mode_chg); /* Re-arm the signal. */
- duplex = 1 - duplex; /* Toggle duplex mode. */
- debug(F101,"mode_chg duplex","",duplex);
- }
-
- /* C K C P U T F -- C-Kermit CONNECT Put Character to Screen */
- /*
- Output is buffered to avoid slow screen writes on fast connections.
- */
- int
- ckcputf() { /* Dump the output buffer */
- int x = 0;
- if (obc > 0) /* If we have any characters, */
- x = conxo(obc,obuf); /* dump them, */
- obp = obuf; /* reset the pointer */
- obc = 0; /* and the counter. */
- return(x); /* Return conxo's return code */
- }
-
- /* C K C P U T C -- C-Kermit CONNECT Put Character to Screen */
- /*
- Output is buffered to avoid slow screen writes on fast connections.
- */
- int
- ckcputc(c) int c; {
- int x;
-
- *obp++ = c & 0xff; /* Deposit the character */
- obc++; /* Count it */
- if (ibc == 0 || /* If input buffer empty */
- obc == OBUFL) { /* or output buffer full */
- debug(F101,"CKCPUTC obc","",obc);
- x = conxo(obc,obuf); /* dump the buffer, */
- obp = obuf; /* reset the pointer */
- obc = 0; /* and the counter. */
- return(x); /* Return conxo's return code */
- } else return(0);
- }
-
- /* C K C G E T C -- C-Kermit CONNECT Get Character */
- /*
- Buffered read from communication device.
- Returns the next character, refilling the buffer if necessary.
- On error, returns ttinc's return code (see ttinc() description).
- Dummy argument for compatible calling conventions with ttinc().
- */
- int
- ckcgetc(dummy) int dummy; {
- int c, n;
-
- debug(F101,"CKCGETC 1 ibc","",ibc); /* Log */
- if (ibc < 1) { /* Need to refill buffer? */
- ibc = 0; /* Yes, reset count */
- ibp = ibuf; /* and buffer pointer */
- debug(F100,"CKCGETC 1 calling ttinc(0)","",0); /* Log */
- c = ttinc(0); /* Read one character, blocking */
- debug(F101,"CKCGETC 1 ttinc(0)","",c); /* Log */
- if (c < 0) { /* If error, return error code */
- return(c);
- } else { /* Otherwise, got one character */
- *ibp++ = c; /* Advance buffer pointer */
- ibc++; /* and count. */
- }
-
- /* Now quickly read any more that might have arrived */
-
- if ((n = ttchk()) > 0) { /* Any more waiting? */
- if (n > (IBUFL - ibc)) /* Get them all at once. */
- n = IBUFL - ibc; /* Don't overflow buffer */
- if ((n = ttxin(n,(CHAR *)ibp)) > 0) {
- ibp += n; /* Advance pointer */
- ibc += n; /* and counter */
- } else return (-1);
- }
- debug(F101,"CKCGETC 2 ibc","",ibc); /* Log how many */
- ibp = ibuf;
- }
- c = *ibp++ & 0xff; /* Get next character from buffer */
- ibc--; /* Reduce buffer count */
- return(c); /* Return the character */
- }
-
- /* C O N E C T -- Perform terminal connection */
-
- int
- conect() {
- PID_T pid; /* Process id of child (modem reader) */
- int n; /* General purpose counter */
- int c; /* c is a character, but must be signed
- integer to pass thru -1, which is the
- modem disconnection signal, and is
- different from the character 0377 */
- int c2; /* A copy of c */
- int csave; /* Another copy of c */
- int num; /* Another counter - used with dgncinb() */
- char ch; /* Ditto here */
-
- #ifdef DYNAMIC
- if (!(ibuf = malloc(IBUFL+1))) { /* Allocate input line buffer */
- printf("Sorry, CONNECT input buffer can't be allocated\n");
- return(0);
- }
- if (!(obuf = malloc(OBUFL+1))) { /* Allocate input line buffer */
- printf("Sorry, CONNECT output buffer can't be allocated\n");
- free(ibuf); ibuf = 0;
- return(0);
- }
- if (!(temp = malloc(TMPLEN+1))) { /* Allocate temporary buffer */
- printf("Sorry, CONNECT temporary buffer can't be allocated\n");
- free(ibuf); ibuf = 0;
- free(obuf); obuf = 0;
- return(0);
- }
- #endif /* DYNAMIC */
-
- if (!local) {
- #ifdef NETCONN
- printf("Sorry, you must SET LINE or SET HOST first\n");
- #else
- printf("Sorry, you must SET LINE first\n");
- #endif /* NETCONN */
- return(0);
- }
- if (backgrd) {
- printf(
- "\r\nSorry, Kermit's CONNECT command can be used only in the foreground\r\n");
- return(0);
- }
- if (speed < 0L && network == 0) {
- printf("Sorry, you must SET SPEED first\n");
- return(0);
- }
- #ifdef TCPSOCKET
- if (network && (nettype != NET_TCPB)) {
- printf("Sorry, network type not supported\n");
- return(0);
- }
- #endif /* TCPSOCKET */
-
-
- if (ttyfd < 0) { /* If communication device not open */
- debug(F111,"ckdcon opening",ttname,0); /* Open it now */
- if (ttopen(ttname,&local,mdmtyp,0) < 0) {
- sprintf(temp,"Sorry, can't open %s",ttname);
- perror(temp);
- debug(F110,"ckdcon open failure",temp,0);
- #ifdef DYNAMIC
- if (ibuf) free(ibuf); ibuf = 0;
- if (obuf) free(obuf); obuf = 0;
- if (temp) free(temp); temp = 0;
- #endif /* DYNAMIC */
- return(0);
- }
- }
- dohangup = 0; /* Hangup not requested yet */
- if (!quiet) {
- #ifdef NETCONN
- if (network) {
- printf("Connecting to host %s",ttname);
- } else {
- #endif /* NETCONN */
- printf("Connecting to %s",ttname);
- if (speed > -1L) printf(", speed %ld",speed);
- #ifdef NETCONN
- }
- #endif /* NETCONN */
- printf(".\r\nThe escape character is %s (ASCII %d).\r\n",
- dbchr(escape),escape);
- printf("Type the escape character followed by C to get back,\r\n");
- printf("or followed by ? to see other options.\r\n");
- if (seslog) {
- printf("(Session logged to %s, ",sesfil);
- printf("%s)\r\n", sessft ? "binary" : "text");
- }
- if (debses) printf("Debugging Display...)\r\n");
- }
-
- /* Condition console terminal and communication line */
-
- if (conbin(escape) < 0) {
- printf("Sorry, can't condition console terminal\n");
- #ifdef DYNAMIC
- if (ibuf) free(ibuf); ibuf = 0;
- if (obuf) free(obuf); obuf = 0;
- if (temp) free(temp); temp = 0;
- #endif /* DYNAMIC */
- return(0);
- }
- debug(F101,"connect cmask","",cmask);
- debug(F101,"connect cmdmsk","",cmdmsk);
- goterr = 0;
- if ((n = ttvt(speed,flow)) < 0) { /* Enter "virtual terminal" mode */
- debug(F101,"CONNECT ttvt","",n);
- goterr = 1; /* Error recovery... */
- tthang(); /* Hang up and close the device. */
- ttclos(0);
- if (ttopen(ttname,&local,mdmtyp,0) < 0) { /* Open it again... */
- sprintf(temp,"Sorry, can't reopen %s",ttname);
- perror(temp);
- #ifdef DYNAMIC
- if (ibuf) free(ibuf); ibuf = 0;
- if (obuf) free(obuf); obuf = 0;
- if (temp) free(temp); temp = 0;
- #endif /* DYNAMIC */
- return(0);
- }
- if (ttvt(speed,flow) < 0) { /* Try virtual terminal mode again. */
- conres(); /* Failure this time is fatal. */
- printf("Sorry, Can't condition communication line\n");
- #ifdef DYNAMIC
- if (ibuf) free(ibuf); ibuf = 0;
- if (obuf) free(obuf); obuf = 0;
- if (temp) free(temp); temp = 0;
- #endif /* DYNAMIC */
- return(0);
- }
- #ifdef NETCONN
- if (network && ttnproto == NP_TELNET)
- tn_ini(); /* Just in case ttopen didn't... */
- #endif /* NETCONN */
- }
- debug(F101,"connect ttvt ok, escape","",escape);
-
- #ifndef NOCSETS
- /* Set up character set translations */
-
- tcs = gettcs(tcsr,tcsl);
-
- if (tcsr == tcsl) { /* Remote and local sets the same? */
- sxo = rxo = NULL; /* If so, no translation. */
- sxi = rxi = NULL;
- } else { /* Otherwise, set up */
- sxo = xls[tcs][tcsl]; /* translation function */
- rxo = xlr[tcs][tcsr]; /* pointers for output functions */
- sxi = xls[tcs][tcsr]; /* and for input functions. */
- rxi = xlr[tcs][tcsl];
- }
- /*
- This is to prevent use of zmstuff() and zdstuff() by translation functions.
- They only work with disk i/o, not with communication i/o. Luckily Russian
- translation functions don't do any stuffing...
- */
- langsv = language;
- #ifndef NOCYRIL
- if (language != L_RUSSIAN)
- #endif /* NOCYRIL */
- language = L_USASCII;
-
- #ifdef SKIPESC
- /*
- We need to activate the "skip escape sequence" feature when:
- (a) translation is elected, and
- (b) the local and/or remote set is 7-bit set other than US ASCII.
- */
- skipesc = (tcs != TC_TRANSP) && /* Not transparent */
- (fcsinfo[tcsl].size == 128 || fcsinfo[tcsr].size == 128) && /* 7 bits */
- (fcsinfo[tcsl].code != FC_USASCII); /* But not ASCII */
- inesc = ES_NORMAL; /* Initial state of recognizer */
- #ifdef COMMENT
- debug(F101,"tcs","",tcs);
- debug(F101,"tcsl","",tcsl);
- debug(F101,"tcsr","",tcsr);
- debug(F101,"fcsinfo[tcsl].size","",fcsinfo[tcsl].size);
- debug(F101,"fcsinfo[tcsr].size","",fcsinfo[tcsr].size);
- #endif /* COMMENT */
- debug(F101,"skipesc","",skipesc);
- #endif /* SKIPESC */
- #endif /* NOCSETS */
-
- /*
- This is a label we jump back to when the lower fork senses the need
- to change modes.
- */
- newfork:
-
- debug(F100,"CONNECT starting readfromcommline task","",0);
- parent_id = getpid(); /* Get pid for signalling */
- signal(SIGUSR1,SIG_IGN); /* Don't kill myself */
-
- /* ENH - DG specifics inserted here - we do an mtask instead of a vfork */
- /* of the code that listens to the comm line and writes to the console */
- /* -- that task is called readfromcommline */
-
- /* ENH - commented next because timeouts should be handled with signals now */
- /* setto(channel(ttyfdout),60); */ /* Set output timeouts to 60 seconds */
- /* setto(channel(ttyfd),2); */ /* Set input timeouts to 2 seconds */
- mfinit(stdout,1); /* Protect output to terminal screen */
- if (mtask(readfromcommline, STACK, TASKID, TASKPRI) != 0) {
- conres(); /* Reset the console. */
- perror("Can't create readfromcommline fork");
- if (!quiet) {
- printf("\r\nCommunications disconnect (Back at %s)\r\n",
- *myhost ? myhost : "local MV system");
- }
- printf("\n");
- what = W_NOTHING; /* So console modes are set right. */
- #ifndef NOCSETS
- language = langsv; /* Restore language */
- #endif /* NOCSETS */
- parent_id = (PID_T) 0; /* Clean up */
- #ifdef DYNAMIC
- if (ibuf) free(ibuf); ibuf = 0;
- if (obuf) free(obuf); obuf = 0;
- if (temp) free(temp); temp = 0;
- #endif /* DYNAMIC */
- return(1);
- } else { /* otherwise start reading from the keyboard (or script) */
-
- what = W_CONNECT; /* Keep track of what we're doing */
- active = 1;
- debug(F101,"CONNECT mtask succeeded, duplex:","",duplex);
-
- /* Catch communication errors or mode changes in lower fork */
-
- if (setjmp(con_env) == 0) { /* Normal entry... */
- sjval = 0; /* Initialize setjmp return code. */
- signal(SIGUSR1,conn_int); /* Routine for child process exit. */
- signal(SIGUSR2,mode_chg); /* Routine for mode change. */
- }
-
- /*
- Here is the big loop that gets characters from the keyboard and sends them
- out the communication device. There are two components to the communication
- path: the connection from the keyboard to C-Kermit, and from C-Kermit to
- the remote computer. The treatment of the 8th bit of keyboard characters
- is governed by SET COMMAND BYTESIZE (cmdmsk). The treatment of the 8th bit
- of characters sent to the remote is governed by SET TERMINAL BYTESIZE
- (cmask). This distinction was introduced in edit 5A(164).
- */
- while (active) {
- #ifndef NOSETKEY
- if (kmptr) { /* Have current macro? */
- debug(F100,"kmptr non NULL","",0);
- if ((c = (CHAR) *kmptr++) == NUL) { /* Get char from it */
- kmptr = NULL; /* If no more chars, */
- debug(F100,"macro empty, continuing","",0);
- continue; /* reset pointer and continue */
- }
- debug(F000,"char from macro","",c);
- } else /* No macro... */
- #endif /* NOSETKEY */
- setto(channel(0),2); /* Set device timeout to 2 secs */
- while (active) { /* Make sure connection still there */
- /* terrible kludge calling dgncinb() directly -- we do
- it so we can set the device timeout and thus prevent
- this read from hanging forever when the remote has
- disconnected -- all so that we'll pop back to the
- prompt when the disconnect occurs
- */
- num = dgncinb(0,&ch,1); /* Get one keyboard char */
- if (num != 1) {
- if ((num == 0) || (num == -2)) /* Keep trying on */
- continue; /* timeout or none */
- else { /* Otherwise it's a*/
- c == -1; /* VS error or EOF */
- break; /* dealt w/ in a sec */
- }
- } else {
- c = ch & 0377; /* Got a good one */
- break; /* Get out of here */
- }
- }
- resto(channel(0)); /* Undo the device timeout */
- if (!active) /* If remote disconnected */
- break; /* Get out */
- if (c == -1) { /* If read() got an error... */
- conoc(BEL); /* Beep */
- break; /* and terminate the read loop */
- }
- /* debug(F111,"** KEYB",dbchr(c),c); */
- c &= cmdmsk; /* Do any requested masking */
- #ifndef NOSETKEY
- /*
- Note: kmptr is NULL if we got character c from the keyboard, and it is
- not NULL if it came from a macro. In the latter case, we must avoid
- expanding it again.
- */
- if (!kmptr && macrotab[c]) { /* Macro definition for c? */
- kmptr = macrotab[c]; /* Yes, set up macro pointer */
- continue; /* and restart the loop, */
- } else c = keymap[c]; /* else use single-char keymap */
- #endif /* NOSETKEY */
- if (
-
- #ifndef NOSETKEY
- !kmptr &&
- #endif /* NOSETKEY */
- ((c & 0x7f) == escape)) { /* Escape character? */
- debug(F000,"connect got escape","",c);
- c = congks(0) & 0177; /* Got esc, get its arg */
- /* No key mapping here */
- doesc(c); /* Now process it */
-
- } else { /* It's not the escape character */
- csave = c; /* Save it before translation */
- /* for local echoing. */
- #ifndef NOCSETS
- #ifndef SKIPESC
- /* Translate character sets */
- if (sxo) c = (*sxo)(c); /* From local to intermediate. */
- if (rxo) c = (*rxo)(c); /* From intermediate to remote. */
- #else
- if (inesc == ES_NORMAL) { /* If not inside escape seq.. */
- /* Translate character sets */
- if (sxo) c = (*sxo)(c); /* Local to intermediate. */
- if (rxo) c = (*rxo)(c); /* Intermediate to remote. */
- }
- if (skipesc) chkaes(c); /* Check escape sequence status */
- #endif /* SKIPESC */
- #endif /* NOCSETS */
- /*
- If Shift-In/Shift-Out is selected and we have a 7-bit connection,
- handle shifting here.
- */
- if (sosi) { /* Shift-In/Out selected? */
- if (cmask == 0177) { /* In 7-bit environment? */
- if (c & 0200) { /* 8-bit character? */
- if (outshift == 0) { /* If not shifted, */
- ttoc(dopar(SO)); /* shift. */
- outshift = 1;
- }
- } else {
- if (outshift == 1) { /* 7-bit character */
- ttoc(dopar(SI)); /* If shifted, */
- outshift = 0; /* unshift. */
- }
- }
- }
- if (c == SO) outshift = 1; /* User typed SO */
- if (c == SI) outshift = 0; /* User typed SI */
- }
- c &= cmask; /* Apply Kermit-to-host mask now. */
- if (c == '\015') {
- if (tnlm /* TEMINAL NEWLINE ON */
- #ifdef TNCODE /* And for TELNET... */
- || (network && ttnproto == NP_TELNET)
- #endif /* TNCODE */
- ) {
- ttoc(dopar('\015')); /* Send CR */
- if (duplex) conoc('\015'); /* Maybe echo CR */
- #ifdef TNCODE
- if (network && !tn_nlm && ttnproto == NP_TELNET)
- c = '\0'; /* Stuff NUL */
- else
- #endif /* TNCODE */
- c = '\012'; /* Stuff LF */
- csave = c;
- }
- } /* Now go on to process LF or NUL */
- #ifdef TNCODE
- /* If user types the 0xff character (TELNET IAC), it must be doubled. */
- else
- if (c == IAC && network && ttnproto == NP_TELNET) {
- /* Send one copy now */
- ttoc(IAC); /* and the other one just below. */
- }
- #endif /* TNCODE */
- /* Send the character */
-
- if (ttoc(dopar(c)) > -1) {
- if (duplex) { /* If half duplex, must echo */
- if (debses)
- conol(dbchr(csave)); /* the original char */
- else /* not the translated one */
- conoc(csave);
- if (seslog) { /* And maybe log it too */
- c2 = csave;
- if (sessft == 0 && csave == '\r')
- c2 = '\n';
- logchar(c2);
- }
- }
- } else if (active){ /* UNIX doesn't check for active */
- perror("\r\nCan't send character");
- break; /* UNIX clears active flag instead */
- }
- }
- }
- midkill(TASKID); /* kill comm line reader task */
- if (sjval == 1) { /* Read error on comm device */
- dohangup = 1;
- #ifdef NETCONN
- if (network) {
- ttclos(0);
- }
- #endif /* NETCONN */
- }
- if (sjval == 2) /* If it was a mode change, go back */
- goto newfork; /* and coordinate with other fork. */
- conres(); /* Reset the console. */
- if (quitnow) doexit(GOOD_EXIT,xitsta); /* Exit now if requested. */
- if (dohangup > 0) {
- #ifndef NODIAL
- if (dohangup > 1) /* If hangup requested, do that. */
- if (mdmhup() < 1) /* Try via modem first */
- #endif /* NODIAL */
- tthang(); /* And make sure we don't hang up */
- dohangup = 0; /* again unless requested again. */
- }
- mfinit(stdout,0); /* Un-protect output to screen */
- what = W_NOTHING; /* So console modes set right. */
- #ifndef NOCSETS
- language = langsv; /* Restore language */
- #endif /* NOCSETS */
- parent_id = (PID_T) 0;
- #ifdef DYNAMIC
- if (ibuf) free(ibuf); ibuf = 0;
- if (obuf) free(obuf); obuf = 0;
- if (temp) free(temp); temp = 0;
- #endif /* DYNAMIC */
- return(1);
- } /* else */
- }
-
- void
- readfromcommline() {
- int c;
- int i;
- int n;
- int tx,x; /* variables needed for tn_doop code */
-
- if (priv_can()) { /* Cancel all privs */
- printf("?setuid error - fatal\n");
- doexit(BAD_EXIT,-1);
- }
- signal(SIGINT, SIG_IGN); /* In case these haven't been */
- signal(SIGQUIT, SIG_IGN); /* inherited from above... */
-
- inshift = outshift = 0; /* Initial shift state. */
- sleep(1); /* Wait for parent's handler setup. */
- ibp = ibuf; /* Initialize input buffering */
- ibc = 0; /* And output buffering. */
- obp = obuf;
- obc = 0;
- debug(F100,"CONNECT starting port task (readfromcommline)","",0);
- while (active) { /* Fresh read, wait for a character. */
- /*
- Get the next communication line character from our internal buffer.
- If the buffer is empty, refill it.
- */
- c = ckcgetc(0); /* Get next character */
- /* debug(F101,"CONNECT c","",c); */
- if (c < 0) {
- active = 0; /* deviation from unix code */
- if (!quiet) { /* Failed... */
- printf("\r\nCommunications disconnect (Back at %s)\r\n",
- *myhost ? myhost : "local MV system");
- if ( c == -3)
- perror("\r\nCan't read character");
- }
- #ifndef NODIAL
- if (mdmhup() < 1)
- #endif /* NODIAL */
- tthang(); /* Hang up our side. */
- sjval = 1; /* Notify parent - kludge */
- for (;;) pause(); /* Wait to be killed */
- }
- debug(F111,"** PORT",dbchr(c),c);
- #ifdef TNCODE
- /* Handle TELNET negotiations here */
- if (c == IAC && network && ttnproto == NP_TELNET) {
- debug(F111,"got IAC from port",dbchr(c),c);
- ckcputf(); /* Dump output buffer */
- tx = tn_doop((c & 0xff),duplex,ckcgetc);
- debug(F111,"tn_doop returns ","",tx);
- if (tx == 0)
- continue;
- else if (tx == -1) { /* I/O error */
- if (active && !quiet)
- printf("\r\nCommunications disconnect (Back at %s)\r\n",
- *myhost ? myhost : "local MV system");
- active = 0;
- sjval = 1; /* Notify parent - kludge */
- for (;;) pause(); /* Wait to be killed. */
- } else if ((tx == 1) && (!duplex)) { /* ECHO change */
- if (parent_id)
- kill(parent_id,SIGUSR2); /* Tell the parent */
- duplex = 1;
- } else if ((tx == 2) && (duplex)) { /* ECHO change */
- if (parent_id)
- kill(parent_id,SIGUSR2);
- duplex = 0;
- } else if (tx == 3) { /* Quoted IAC */
- c = 255;
- } else continue; /* Negotiation OK, get next char. */
- }
- #endif /* TNCODE */
- if (debses) { /* Output character to screen */
- char *s; /* Debugging display... */
- s = dbchr(c);
- while (*s)
- ckcputc(*s++);
- } else { /* or regular display ... */
- c &= cmask; /* Apply Kermit-to-remote mask */
- if (sosi) { /* Handle SI/SO */
- if (c == SO) { /* Shift Out */
- inshift = 1;
- continue;
- } else if (c == SI) { /* Shift In */
- inshift = 0;
- continue;
- }
- if (inshift) c |= 0200;
- }
- #ifndef NOCSETS
- #ifndef SKIPESC
- /* Translate character sets */
- if (sxi) c = (*sxi)(c);
- if (rxi) c = (*rxi)(c);
- #else
- if (inesc == ES_NORMAL) {
- /* Translate character sets */
- if (sxi) c = (*sxi)(c);
- if (rxi) c = (*rxi)(c);
- }
- if (skipesc) chkaes(c); /* Adjust escape sequence status */
- #endif /* SKIPESC */
- #endif /* NOCSETS */
- c &= cmdmsk; /* Apply command mask. */
- if (c == CR && tt_crd) { /* SET TERM CR-DISPLAY CRLF ? */
- ckcputc(c); /* Yes, output CR */
- if (seslog) logchar(c);
- c = LF; /* and insert a linefeed */
- }
- ckcputc(c); /* Output to screen */
- if (seslog) logchar(c); /* Take care of session log */
- }
- }
- }
-
-
-
- /* H C O N N E -- Give help message for connect. */
-
- int
- hconne() {
- int c;
- static char *hlpmsg[] = {
- "\r\n ? for this message",
- "\r\n 0 (zero) to send a null",
- "\r\n B to send a BREAK",
- #ifdef NETCONN
- "\r\n I to send a network interrupt packet",
- #ifdef TCPSOCKET
- "\r\n A to send Are You There?",
- #endif /* TCPSOCKET */
- #endif /* NETCONN */
- "\r\n H to hangup and close the connection",
- "\r\n Q to hangup and quit Kermit",
- "\r\n S for status",
- "\r\n ! to push to local shell",
- "\r\n \\ backslash code:",
- "\r\n \\nnn decimal character code",
- "\r\n \\Onnn octal character code",
- "\r\n \\Xhh hexadecimal character code",
- "\r\n terminate with carriage return.",
- "\r\n type the escape character twice to send the escape character",
- "\r\n space-bar to resume the CONNECT command\r\n\r\n",
- "" };
- conol("\r\nPress C to return to ");
- conol(*myhost ? myhost : "the C-Kermit prompt");
- conol(", or:");
- conola(hlpmsg); /* Print the help message. */
- conol("Command>"); /* Prompt for command. */
- c = congks(0) & 0177; /* Get character, strip any parity. */
- /* No key mapping or translation here */
- if (c != CMDQ)
- conoll("");
- return(c); /* Return it. */
- }
-
-
- /* D O E S C -- Process an escape character argument */
-
- VOID
- #ifdef CK_ANSIC
- doesc(char c)
- #else
- doesc(c) char c;
- #endif /* CK_ANSIC */
- /* doesc */ {
- CHAR d, buf[3];
-
- while (1) {
- if (c == escape) { /* Send escape character */
- d = dopar(c); ttoc(d); return;
- } else /* Or else look it up below. */
- if (isupper(c)) c = tolower(c);
-
- switch(c) {
-
- case 'c': /* Close connection */
- case '\03':
- active = 0; conol("\r\n"); return;
-
- case 'b': /* Send a BREAK signal */
- case '\02':
- ttsndb(); return;
-
- #ifdef NETCONN
- case 'i': /* Send Interrupt */
- case '\011':
- #ifdef TCPSOCKET
- #ifndef IP
- #define IP 244
- #endif /* IP */
- if (network && ttnproto == NP_TELNET) { /* TELNET */
- buf[0] = (CHAR) IAC; /* I Am a Command */
- buf[1] = (CHAR) IP; /* Interrupt Process */
- ttol(buf,2);
- } else
- #endif /* TCPSOCKET */
- conoc(BEL);
- return;
- #ifdef TCPSOCKET
- case 'a': /* "Are You There?" */
- case '\01':
- #ifndef AYT
- #define AYT 246
- #endif /* AYT */
- if (network && ttnproto == NP_TELNET) {
- buf[0] = (CHAR) IAC; /* I Am a Command */
- buf[1] = (CHAR) AYT; /* Are You There? */
- ttol(buf,2);
- } else conoc(BEL);
- return;
- #endif /* TCPSOCKET */
- #endif /* NETCONN */
-
- case 'h': /* Hangup */
- /* case '\010': */ /* Too dangerous */
- dohangup = 2; active = 0; conol("\r\nHanging up "); return;
-
- case 'q':
- quitnow = 1; active = 0; conol("\r\n"); return;
-
- case 's': /* Status */
- sprintf(temp,
- "\r\nConnected %s %s", network ? "to" : "through", ttname);
- conol(temp);
- if (speed >= 0L) {
- sprintf(temp,", speed %ld",speed); conol(temp);
- }
- sprintf(temp,", %d terminal bits",(cmask == 0177) ? 7 : 8);
- conol(temp);
- if (parity) {
- conol(", ");
- switch (parity) {
- case 'e': conol("even"); break;
- case 'o': conol("odd"); break;
- case 's': conol("space"); break;
- case 'm': conol("mark"); break;
- }
- conol(" parity");
- }
- if (seslog) {
- conol(", logging to "); conol(sesfil);
- }
- conoll("");
- if (!network) shomdm();
- return;
-
- case '?': /* Help */
- c = hconne(); continue;
-
- case '0': /* Send a null */
- c = '\0'; d = dopar(c); ttoc(d); return;
-
- #ifndef NOPUSH
- case '@': /* Start inferior command processor */
- case '!':
- conres(); /* Put console back to normal */
- zshcmd(""); /* Fork a shell. */
- if (conbin(escape) < 0) {
- printf("Error resuming CONNECT session\n");
- active = 0;
- }
- return;
- #endif /* NOPUSH */
-
- case SP: /* Space, ignore */
- return;
-
- default: /* Other */
- if (c == CMDQ) { /* Backslash escape */
- int x;
- kbp = kbuf;
- *kbp++ = c;
- while (((c = (congks(0) & cmdmsk)) != '\r') && (c != '\n'))
- *kbp++ = c;
- *kbp = NUL; kbp = kbuf;
- x = xxesc(&kbp); /* Interpret it */
- if (x >= 0) { /* No key mapping here */
- c = dopar(x);
- ttoc(c);
- return;
- } else { /* Invalid backslash code. */
- conoc(BEL);
- return;
- }
- }
- conoc(BEL); return; /* Invalid esc arg, beep */
- }
- }
- }
-
- VOID
- #ifdef CK_ANSIC
- logchar(char c)
- #else
- logchar(c) char c;
- #endif /* CK_ANSIC */
- /* logchar */ { /* Log character c to session log */
- if (seslog)
- if ((sessft != 0) ||
- (c != '\r' &&
- c != '\0' &&
- c != XON &&
- c != XOFF))
- if (zchout(ZSFILE,c) < 0) {
- conoll("");
- conoll("ERROR WRITING SESSION LOG, LOG CLOSED!");
- seslog = 0;
- }
- }
-